/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bs.extensoesSwing;

import com.bs.util.RefletorDeCampoBean;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JRootPane;

/**
 *
 * @author Bone
 */
public class CampoSugestao extends CampoTexto {

    private String sQuery;
    private EntityManager entityManager = new com.bs.persistencia.EntityManager();//  = javax.persistence.Persistence.createEntityManagerFactory("devPU").createEntityManager();
    private Query query;
    private String parametro;
    private List<String> listaView;
    private List<Object> listaRetorno;
    private String campo;
    private String campoRetorno;
    private String campoExibicao;
    private Object itemSelecionado;
    private int indiceSelecionado = -1;
    private Color borderListColor = Color.BLACK;
    private boolean emFoco = false;

    public CampoSugestao() {
        addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_DOWN:
                        itemAvancar();
                        return;
                    case KeyEvent.VK_UP:
                        itemAnterior();
                        return;
                }
                if (!e.isControlDown()) {
                    pesquisar();
                }

            }
        });
        addFocusListener(new FocusAdapter() {

            @Override
            public void focusGained(FocusEvent e) {
                super.focusGained(e);
                emFoco = true;
            }

            @Override
            public void focusLost(FocusEvent e) {
                super.focusLost(e);
                if (itemSelecionado != null) {
                    setText(RefletorDeCampoBean.get(itemSelecionado, campo).toString());
                }
                listaView = null;
                getRootPane().validate();
                getRootPane().repaint();
                emFoco = false;
            }
        });
    }

    public void pesquisar() {
        String valor = this.getText();
        if (valor.equals("")) {
            getRootPane().repaint();
            if (listaView != null) {
                listaView.clear();
            }
            setItemSelecionado(null);
            return;
        }
        if (query == null) {
            query = entityManager.createQuery(sQuery);
        }
        query.setParameter(parametro, "%" + valor + "%");
        ArrayList<String> result = new ArrayList<String>();
        if (listaView == null) {
            listaView = new ArrayList<String>();
        } else {
            if (getRootPane() != null) {
                getRootPane().repaint();
            }
        }
        listaRetorno = query.getResultList();

        for (Object o : listaRetorno) {
            result.add(RefletorDeCampoBean.get(o, campoExibicao).toString());
        }

        listaView.clear();
        listaView.addAll(result);
        if (!listaView.isEmpty()) {
            setIndiceSelecionado(0);
        } else {
            setIndiceSelecionado(-1);
        }

    }

    private void itemAvancar() {
        if (indiceSelecionado != -1) {
            int size = listaRetorno.size();
            if (indiceSelecionado < size - 2) {
                setIndiceSelecionado(indiceSelecionado + 1);
            } else {
                setIndiceSelecionado(size - 1);
            }

        }
    }

    private void itemAnterior() {
        if (indiceSelecionado != -1) {
            if (indiceSelecionado > 0) {
                setIndiceSelecionado(indiceSelecionado - 1);
            } else {
                setIndiceSelecionado(0);
            }
        }
    }

    public String getParametro() {
        return parametro;
    }

    public void setParametro(String parametro) {
        this.parametro = parametro;
    }

    public String getCampo() {
        return campo;
    }

    public void setCampo(String campo) {
        String old = this.campo;
        this.campo = campo;
        if(campoExibicao == null ? true : campoExibicao.equals("") ){
            setCampoExibicao(campo);
        }
        firePropertyChange("campo", old, campo);
    }

    public List getListaRetorno() {
        return listaRetorno;
    }

    public void setListaRetorno(List listaRetorno) {
        this.listaRetorno = listaRetorno;
    }

    public int getIndiceSelecionado() {
        return indiceSelecionado;
    }

    public void setIndiceSelecionado(int indiceSelecionado) {
        int old = this.indiceSelecionado;
        if (indiceSelecionado != -1) {
            setItemSelecionado(listaRetorno.get(indiceSelecionado));
        } else {
            setItemSelecionado(null);
        }
        this.indiceSelecionado = indiceSelecionado;
        firePropertyChange("indiceSelecionado", old, indiceSelecionado);
    }

    public Object getItemSelecionado() {

        return itemSelecionado;
    }

    public void setItemSelecionado(Object itemSelecionado) {
        Object old = this.itemSelecionado;
        this.itemSelecionado = itemSelecionado;
        if (itemSelecionado != null && !emFoco) {
            this.setText(RefletorDeCampoBean.get(itemSelecionado, campo).toString());
            this.setSelecionarAoEntrar(true);
        } else {
            if (itemSelecionado == null) {
                this.setText("");
            }
        }
        firePropertyChange("itemSelecionado", old, itemSelecionado);
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public String getsQuery() {
        return sQuery;
    }

    public void setsQuery(String sQuery) {
        this.sQuery = sQuery;
    }

    public Color getBorderListColor() {
        return borderListColor;
    }

    public void setBorderListColor(Color borderListColor) {
        this.borderListColor = borderListColor;
    }

    public String getCampoRetorno() {
        return campoRetorno;
    }

    public void setCampoRetorno(String campoRetorno) {
        this.campoRetorno = campoRetorno;
    }


    @Override
    public void paint(Graphics g) {
        super.paint(g);
        if (listaView != null) {
            if (!listaView.isEmpty()) {
                Font fonte = this.getFont();
                FontMetrics metrics = getFontMetrics(fonte);
                Point local;
                int contResult = 0;
                int w = getWidth();
                for (String s : listaView) {
                    int sW = metrics.stringWidth(s);
                    if (sW > w) {
                        w = sW + 10;
                    }
                }
                int h = listaView.size() * metrics.getHeight() + (listaView.size() * 2);
                boolean painelPrincipal = false;
                Container ct = this;
                while(!painelPrincipal){
                    
                    if(ct instanceof JDialog ||ct instanceof  JFrame ||
                            ct instanceof JRootPane || ct instanceof JLayeredPane){
                        painelPrincipal = true;
                    }else{
                        ct = ct.getParent();
                    }
                }
                // Imprime o painel que comportará os itens.
                Graphics gp =ct.getGraphics();
                gp.setColor(this.getForeground());
                // Obtem o local absoluto do componente.
                local = new Point(this.getLocationOnScreen().x - ct.getLocationOnScreen().x,
                        this.getLocationOnScreen().y - ct.getLocationOnScreen().y);
                for (contResult = 0; contResult < listaView.size(); contResult++) {
                    int posX, posY, largura, altura;
                    posX = (int) local.getX();
                    posY = (int) (((this.getHeight() / 2) * 3) + 6 + local.getY() + (contResult * (metrics.getHeight())));
                    largura = w;
                    altura = metrics.getHeight();
                    if (indiceSelecionado == contResult) {
                        gp.setColor(this.getSelectionColor());
                    } else {
                        gp.setColor(this.getBackground());
                    }
                    gp.fillRect(posX, posY - metrics.getHeight(), largura, altura);
                    gp.setColor(borderListColor);
                    gp.drawRect(posX, posY - metrics.getHeight(), largura, altura);
                    gp.setColor(this.getForeground());
                    gp.drawString(listaView.get(contResult), posX, posY);
                }

            }
        }
        //atualizarLista = false;
    }

    public String getCampoExibicao() {
        return campoExibicao;
    }

    public void setCampoExibicao(String campoExibicao) {
        String old = this.campoExibicao;
        this.campoExibicao = campoExibicao;
        firePropertyChange("campoExibicao", old, campoExibicao);
    }

    public Object getValor() {
        return RefletorDeCampoBean.get(itemSelecionado, campoRetorno);
    }
}
